Pagina iniziale | Navigazione |
Google

Linguaggio di programmazione

Nell'informatica, un linguaggio di programmazione č un linguaggio formale dotato di una sintassi ben definita, in termini di notazione BNF, che viene utilizzato per scrivere programmi che realizzano algoritmi. Sono nati per facilitare la programmazione dei calcolatori rendendo possibile descrivere gli algoritmi e le strutture dei dati in una forma piů vicina a quella del linguaggio umano scritto.

Tutti i linguaggi di programmazione esistenti possiedono (almeno) questi due concetti chiave:

Variabile: un dato o un insieme di dati, noti o ignoti, giĂ  memorizzati o da memorizzare; ad una variabile corrisponde sempre, da qualche parte, un certo numero (fisso o variabile) di locazioni di memoria che vengono allocate, cioč riservate, per contenere i dati stessi. Molti linguaggi inoltre classificano le variabili in tipi, con differenti proprietĂ  (stringhe di testo, numeri, liste, atomi ecc.).
Istruzione: un comando, una azione concreta, oppure una regola descrittiva: anche il concetto di istruzione č molto variabile fra classi di linguaggi diverse. A prescindere dal particolare linguaggio però, ogni volta che un'istruzione viene eseguita, lo stato interno del calcolatore (che sia lo stato reale della macchina oppure un ambiente virtuale, teorico, creato dal linguaggio) cambia.

Programmare in un dato linguaggio di programmazione significa essenzialmente scrivere un semplice file di testo ASCII, chiamato codice sorgente. I font, i colori e in generale l'aspetto grafico sono irrilevanti ai fini della programmazione in sĂ©: per questo i programmatori non usano programmi di videoscrittura ma degli editor di testo (come emacs e brief) che invece offrono funzioni avanzate di trattamento testi (espressioni regolari, sostituzioni condizionali e ricerche su file multipli, possibilitĂ  di richiamare strumenti esterni ecc). Se un dato editor č in grado di lavorare a stretto contatto con gli altri strumenti di lavoro (compilatore, linker, interprete ecc.: vedi piů avanti) allora piů che di semplice editor si parla di IDE o ambiente di sviluppo integrato.

Il codice sorgente, contenente le istruzioni da eseguire e (spesso) alcuni dati noti e costanti, può essere poi eseguito passandolo ad un interprete che eseguirĂ  le istruzioni in esso contenute, il che č la prassi normale per i linguaggi di scripting; oppure può venire compilato, cioč tradotto in istruzioni di linguaggio macchina da un programma compilatore: il risultato č un file binario eseguibile che non ha bisogno di altri programmi per andare in esecuzione, ed č anche molto piů veloce di un programma interpretato. La compilazione č la norma per tutti i linguaggi di programmazione di uso generale; ma esistono le eccezioni, come il linguaggio Java. =Linguaggi compilati e linguaggi interpretati= Questi due metodi di creazione ed esecuzione di un programma presentano entrambi vantaggi e svantaggi: il maggior vantaggio della compilazione č senz'altro l'efficienza nettamente superiore in termini di prestazioni, al prezzo del restare vincolati ad una piattaforma (combinazione di architettura hardware e sistema operativo) particolare; un linguaggio interpretato invece non ha, in linea di massima, questa dipendenza ma č piů lento e richiede piů memoria in fase di esecuzione.

Table of contents
1 La compilazione
2 L'interpretazione
3 Imperativi
4 Funzionali
5 Dichiarativi (o logici)
6 Caratteristiche intrinseche
7 Caratteristiche esterne

La compilazione

Esistono principalmente due tipi differenti di compilazione: la compilazione dinamica e quella statica. La differenza fra le due sta nel modo di considerare le funzioni ausiliarie usate nel programma: nella compilazione dinamica, il file di programma risultante č molto piccolo, perchč non contiene le funzioni ausiliarie ma solo dei rimandi alle librerie esterne che le contengono, che vengono caricate dal sistema operativo al momento del lancio del programma stesso (linking dinamico; le librerie esterne sono le DLL, Dinamyc Linking Libraries).

Nella compilazione statica, invece, tutte le funzioni che il programma usa sono contenute nel suo file eseguibile, che č quindi molto piů grande. In genere si preferisce la compilazione dinamica, in modo da creare programmi piccoli, assumendo che le DLL necessarie siano giĂ  presenti nel sistema o distribuendole insieme al programma.

La compilazione offre numerosi vantaggi, primo fra tutti il fatto di ottenere eseguibili velocissimi adattando vari parametri di questa fase all'hardware a disposizione; ma ha lo svantaggio principale nel fatto che bisogna ricompilare ogni volta che si cambia sistema operativo e hardware su cui ci si basa. Risulta evidente che occorre fare n ricompilazioni per ogni modifica se si vuole rendere disponibile il programma su piů piattaforme.

L'interpretazione

Per cercare di eliminare questo problema si č tentato di creare altri linguaggi che si potessero basare soltanto su librerie compilate (componenti) ad hoc per ogni piattaforma, mentre il loro codice eseguibile viene interpretato e quindi non c'č la necessitĂ  di una compilazione su ogni tipologia di macchina su cui viene eseguito. Il grosso difetto di questi linguaggi č la lentezza e le dimensioni maggiori degli eseguibili; però hanno il grosso pregio di permettere di usare lo stesso file su piů piattaforme.

I linguaggi compilati sono usati quindi per tutti quei software che hanno necessitĂ  di prestazioni, accesso a determinate caratteristiche hardware o ridotte dimensioni degli eseguibili; mentre si usano linguaggi interpretati per creare software che svolgono operazioni non critiche che non necessitano di ottimizzazioni riguardanti velocitĂ  o dimensioni, ma che traggono piů vantaggio del fatto che possono ignorare in molti casi la piattaforma su cui sono eseguiti.

Ci sono vari tentativi per rendere i compilatori multipiattaforma creando un livello intermedio, una sorta di semi-interpretazione; d'altro canto per i linguaggi interpretati ci sono tentativi per generare delle compilazioni (o semi-compilazioni) automatiche specifiche per la macchina su cui sono eseguiti.

=Storia= Il primo linguaggio di programmazione della storia č a rigor di termini il PlankalkĂĽl di Konrad Zuse, sviluppato da lui nella svizzera neutrale durante la II guerra mondiale e pubblicato nel 1946; ma non venne mai realmente usato per programmare.

La programmazione dei primi elaboratori veniva fatta invece in Shortcode, da cui poi si č evoluto l'assembly o assembler, che costituisce una rappresentazione simbolica del linguaggio macchina. La sola forma di controllo di flusso č l'istruzione di salto condizionato, che porta a scrivere programmi molto difficili da seguire logicamente per via dei continui salti da un punto all'altro del codice.

La maggior parte dei linguaggi di programmazione successivi cercarono di astrarsi da tale livello basilare, dando la possibilitĂ  di rappresentare strutture dati e strutture di controllo piů generali e piů vicine alla maniera (umana) di rappresentare i termini dei problemi per i quali ci si prefigge di scrivere programmi. Tra i primi linguaggi ad alto livello a raggiungere una certa popolaritĂ  ci fu il Fortran, creato nel 1957 da John Backus, da cui derivò successivamente il BASIC (1964): oltre al salto condizionato, reso con l'istruzione IF, questa nuova generazione di linguaggi introduce nuove strutture di controllo di flusso come i cicli WHILE e FOR e le istruzioni CASE e SWITCH: in questo modo diminuisce molto il ricorso alle istruzioni di salto (GOTO e IF), cosa che rende il codice piů chiaro ed elegante, e quindi piů facilmente manutenibile.

Dopo la comparsa del Fortran nacquero una serie di altri linguaggi di programmazione storici, che implementarono una serie di idee e paradigmi innovativi: i piů importanti sono l'ALGOL (1960) e il Lisp (1959). Tutti i linguaggi di programmazione oggi esistenti possono essere considerati discendenti da uno o piů di questi primi linguaggi, di cui mutuano molti concetti di base; l'ultimo grande progenitore dei linguaggi moderni fu il Simula (1967), che introdusse per primo il concetto (allora appena abbozzato) di oggetto software.

Nel 1970 Niklaus Wirth pubblica il Pascal, il primo linguaggio strutturato, a scopo didattico; nel 1972 dal BCPL nascono prima il B (rapidamente dimenticato) e poi il C, che invece fu fin dall'inizio un grande successo. Nello stesso anno compare anche il Prolog, finora unico esempio di linguaggio dichiarativo, che pur non essendo utilizzato per il normale lavoro di programmazione a causa della sua inefficienza rappresenta una possibilitĂ  teorica estremamente affascinante.

Con i primi mini e microcomputer e le ricerche a Palo Alto, nel 1983 vede la luce Smalltalk, il primo linguaggio realmente e completamente ad oggetti, che si ispira al Simula e al Lisp: anche lui poco o nulla utilizzato in pratica, ha però una influenza enorme sulla teoria dei linguaggi di programmazione. Suo derivato diretto č l'Eiffel (1986), ma influenza profondamente anche il C++ (che esce nello stesso anno dell'Eiffel) e successivamente Java, classe 1995.

=Classi di linguaggi=

Imperativi

Strutturati

Orientati ad oggetti

Funzionali

Dichiarativi (o logici)

Il Prolog č stato il primo rappresentante di questa classe. Nati a partire da un progetto per un dimostratore automatico di teoremi, i linguaggi dichiarativi rappresentano un modo completamente nuovo di concepire l'elaborazione dei dati: invece di una lista di comandi, un programma in un linguaggio dichiarativo č una lista di regole che descrivono le proprietĂ  dei dati e i modi in cui questi possono trasformarsi. Le variabili non vengono mai assegnate (l'assegnamento non esiste), ma istanziate al momento dell'applicazione in una determinata regola; l'esecuzione del programma consiste nell'applicazione ripetuta delle regole disponibili fino a trovare una catena di regole e trasformazioni che consente di stabilire se il risultato desiderato č vero o no.

Non esistono nč cicli, nč salti, nč un ordine rigoroso di esecuzione; affinchč sia possibile usarli in un programma dichiarativo, tutti i normali algoritmi devono essere riformulati in termini ricorsivi e di backtracking; questo rende la programmazione con questi linguaggi una esperienza del tutto nuova e richiede di assumere un modo di pensare radicalmente diverso, perchč piů che calcolare un risultato si richiede di dimostrarne il valore esatto. A fronte di queste richieste, i linguaggi dichiarativi consentono di raggiungere risultati eccezionali quando si tratta di manipolare gruppi di enti in relazione fra loro.

=Linguaggi paralleli= I moderni supercomputer e - ormai - tutti i calcolatori di fascia alta e media sono equipaggiati con piů CPU. Come ovvia conseguenza, questo richiede la capacitĂ  di sfruttarle; per questo sono stati sviluppati dapprima il multithreading, cioč la capacitĂ  di lanciare piů parti dello stesso programma contemporaneamente su CPU diverse, e in seguito alcuni linguaggi studiati in modo tale da poter individuare da soli, in fase di compilazione, le parti di codice da lanciare in parallelo. =Linguaggi di scripting= I linguaggi di questo tipo nacquero come linguaggi batch: vale a dire liste di comandi di programmi interattivi che invece di venire digitati uno ad uno su una linea di comando, potevano essere salvati in un file, che diventava così una specie di comando composto che si poteva eseguire in modalitĂ  batch per automatizzare compiti lunghi e ripetitivi. I primi linguaggi di scripting sono stati quelli delle shell Unix; successivamente, vista l'utilitĂ  del concetto molti altri programmi interattivi iniziarono a permettere il salvataggio e l'esecuzione di file contenenti liste di comandi, oppure il salvataggio di registrazioni di comandi visuali (le cosidette Macro dei programmi di videoscrittura, per esempio).

Il passo successivo fu quello di far accettare a questi programmi anche dei comandi di salto condizionato e delle istruzioni di ciclo, regolati da simboli associati ad un certo valore: in pratica implementare cioč l'uso di variabili. Ormai molti programmi nati per tutt'altro scopo offrono agli utenti la possibilitĂ  di programmarli in modo autonomo tramite linguaggi di scripting piů o meno proprietari. Molti di questi linguaggi hanno finito per adottare una sintassi molto simile a quella del C: altri invece, come il Perl e il Python, sono stati sviluppati ex novo allo scopo. Visto che nascono tutti come feature di altri programmi, tutti i linguaggi di scripting hanno in comune il fato di essere linguaggi interpretati, cioč eseguiti da un altro programma (il programma madre o un suo modulo).

=Valutare un linguaggio di programmazione= Non ha senso, in generale, parlare di linguaggi migliori o peggiori, o di linguaggi migliori in assoluto: ogni linguaggio nasce per affrontare una classe di problemi piů o meno ampia, in un certo modo e in un certo ambito. Però, dovendo dire se un dato linguaggio sia adatto o no per un certo uso, č necessario valutare le caratteristiche dei vari linguaggi.

Caratteristiche intrinseche

Sono le qualitĂ  del linguaggio in sč, determinate dalla sua sintassi e dalla sua architettura interna. Influenzano direttamente il lavoro del programmatore, condizionandolo. Non dipendono nč dagli strumenti usati (compilatore/interprete, IDE, linker) nč dal sistema operativo o dal tipo di macchina.

EspressivitĂ 

È la facilitĂ  e la semplicitĂ  con cui si può scrivere un dato algoritmo in un dato linguaggio; può dipendere dal tipo di algoritmo, se il linguaggio in questione č nato per affrontare certe particolari classi di problemi. In generale se un certo linguaggio consente di scrivere algoritmi con poche istruzioni, in modo chiaro e leggibile, la sua espressivitĂ  č buona.

Didattica

La semplicitĂ  del linguaggio e la rapiditĂ  con cui lo si può imparare. Il BASIC, per esempio, č un linguaggio facile da imparare: poche regole, una sintassi molto chiara e limiti ben definiti fra quello che č permesso e quello che non lo č. Il Pascal non solo ha i pregi del BASIC ma educa anche il neo-programmatore ad adottare uno stile corretto che evita molti errori e porta a scrivere codice migliore. Al contrario, il C non č un linguaggio didattico perchč pur avendo poche regole ha una semantica molto complessa, a volte oscura, che lo rende molto efficiente ed espressivo ma richiede tempo per essere padroneggiata.

LeggibilitĂ 

La facilitĂ  con cui, leggendo un codice sorgente, si può capire cosa fa e come funziona. La leggibilitĂ  dipende non solo dal linguaggio ma anche dallo stile di programmazione di chi ha creato il programma: tuttavia la sintassi di un linguaggio può facilitare o meno il compito. Non č detto che un linguaggio leggibile per un profano lo sia anche per un esperto: in generale le abbreviazioni e la concisione consentono a chi giĂ  conosce un linguaggio di concentrarsi meglio sulla logica del codice senza perdere tempo a leggere, mentre per un profano č piů leggibile un linguaggio molto prolisso. A volte, un programma molto complesso e poco leggibile in un dato linguaggio può diventare assolutamente semplice e lineare se riscritto in un linguaggio di classe differente, piů adatta.

Robustezza

È la capacitĂ  del linguaggio di prevenire, nei limiti del possibile, gli errori di programmazione. Di solito un linguaggio robusto si ottiene adottando un controllo molto stretto sui tipi di dati e una sintassi chiara e molto rigida; altri sistemi sono l'implementare un garbage collector, limitando (a prezzo di una certa perdita di efficienza) la creazione autonoma di nuove entitĂ  di dati e quindi l'uso dei puntatori, che possono introdurre bug molto difficili da scoprire.

L'esempio piů comune di linguaggio robusto č il Pascal, che essendo nato a scopo didattico presuppone sempre che una irregolaritĂ  nel codice sia frutto di un errore del programmatore; mentre l'assembler č l'esempio per antonomasia di linguaggio totalmente libero, in cui niente vincola il programmatore (e se scrive codice pericoloso o errato, non c'č niente che lo avverta).

ModularitĂ 

Quando un linguaggio facilita la scrittura di parti di programma indipendenti (moduli) viene definito modulare. I moduli semplificano la ricerca e la correzione degli errori, permettendo di isolare rapidamente la parte di programma che mostra il comportamento errato e modificarla senza timore di introdurre conseguenze in altre parti del programma stesso. Questo si ripercuote positivamente sulla manutenibilitĂ  del codice; inoltre permette di riutilizzare il codice scritto in passato per nuovi programmi, apportando poche modifiche. In genere la modularitĂ  si ottiene con l'uso di sottoprogrammi (subroutine, procedure, funzioni) e con la pogrammazione ad oggetti.

FlessibilitĂ 

La possibilitĂ  di adattare il linguaggio, estendendolo con la definizione di nuovi comandi e nuovi operatori. I linguaggi classici come il BASIC, il Pascal e il Fortran non hanno questa capacitĂ , che invece č presente nei linguaggi dichiarativi, in quelli funzionali e nei linguaggi imperativi ad oggetti piů recenti come il C++ e Java.

GeneralitĂ 

La facilitĂ  con cui il linguaggio si presta a codificare algoritmi e soluzioni di problemi in campi diversi. Di solito un linguaggio molto generale, per esempio il C, risulta meno espressivo e meno potente in una certa classe di problemi di quanto non sia un linguaggio specializzato in quella particolare nicchia, che in genere č perciò una scelta migliore finchč il problema da risolvere non esce da quei confini.

Efficienza

La velocitĂ  di esecuzione e l'uso oculato delle risorse del sistema su cui il programma finito gira.
In genere i programmi scritti in linguaggi molto astratti tendono ad essere lenti e voraci di risorse, poichč lavorano entro un modello che non riflette la reale struttura dell'hardware ma č una cornice concettuale, che deve essere ricreata artificialmente; in compenso facilitano molto la vita del programmatore poichč lo sollevano dalla gestione di numerosi dettagli, accelerando lo sviluppo di nuovi programmi ed eliminando intere classi di errori di programmazione possibili. Viceversa un linguaggio meno astratto ma piů vicino alla reale struttura di un computer genererĂ  programmi molto piccoli e veloci ma a costo di uno sviluppo piů lungo e difficoltoso.

Coerenza

L'applicazione dei principi base di un linguaggio in modo uniforme in tutte le sue parti.
Un linguaggio coerente č un linguaggio facile da prevedere e da imparare, perchč una volta appresi i principi base questi sono validi sempre e senza (o con poche) eccezioni.

Caratteristiche esterne

Viste le qualitĂ  dei linguaggi, vediamo quelle degli ambienti in cui operano. Un programmatore lavora con strumenti software, la cui qualitĂ  e produttivitĂ  dipende da un insieme di fattori che vanno pesati anch'essi in funzione del tipo di programmi che si intende scrivere.

Diffusione

Il numero di programmatori nel mondo che usa il tale linguaggio. Ovviamente piů č numerosa la comunitĂ  dei programmatori tanto piů č facile trovare materiale, aiuto, librerie di funzioni, documentazione, consigli. Inoltre ci sono un maggior numero di software house che producono strumenti di sviluppo per quel linguaggio, e di qualitĂ  migliore.

Standardizzazione

Un produttore di strumenti di sviluppo sente sempre la tentazione di introdurre delle variazioni sintattiche o delle migliorie piů o meno grandi ad un linguaggio, originando un dialetto del linguaggio in questione e fidelizzando così i programmatori al suo prodotto: ma piů dialetti esistono, piů la comunitĂ  di programmatori si frammenta in sottocomunitĂ  piů piccole e quindi meno utili. Per questo č importante l'esistenza di uno
standard per un dato linguaggio che ne garantisca certe caratteristiche, in modo da evitarne la dispersione. Quando si parla di Fortran 77, Fortran 90, C 99 ecc. si intende lo standard sintattico e semantico del tale linguaggio approvato nel tale anno, in genere dall'ANSI o dall'ISO.

IntegrabilitĂ 

Dovendo scrivere programmi di una certa dimensione, č molto facile trovarsi a dover integrare parti di codice precedente scritte in altri linguaggi: se un dato linguaggio di programmazione consente di farlo facilmente, magari attraverso delle procedure standard, questo č decisamente un punto a suo favore. In genere tutti i linguaggi "storici" sono bene integrabili, con l'eccezione di alcuni, come lo Smalltalk, creati piů per studio teorico che per il lavoro reale di programmazione.

PortabilitĂ 

La possibilitĂ  che portando il codice scritto su una certa piattaforma (CPU + architettura + sistema operativo) su un'altra, questo funzioni subito, senza doverlo modificare. A questo scopo č molto importante l'esistenza di uno standard del linguaggio, anche se a volte si può contare su degli standard de facto come il C K&R o il Delphi.

= Articoli correlati =


GNU Fdl - it.Wikipedia.org




Google | 

Enciclopedia |  La Divina Commedia di Dante |  Mappa | : A |  B |  C |  D |  E |  F |  G |  H |  I |  J |  K |  L |  M |  N |  O |  P |  Q |  R |  S |  T |  U |  V |  W |  X |  Y |  Z |